﻿using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Microsoft.EnterpriseManagement;
using Microsoft.EnterpriseManagement.Common;
using Microsoft.EnterpriseManagement.Configuration;
using Microsoft.Win32;

namespace System.ServiceManager.Facade
{
    public partial class SCSMServer
    {
        private static IncidentSettings incidentSettings;
        private static ActivitySettings activitySettings;
        private static ChangeManagementSettings changeManagementSettings;
        private static EnterpriseManagementGroup emg;

        private static Dictionary<Guid,ManagementPack> mpCache = new Dictionary<Guid, ManagementPack>();

 

        public static bool IsConnected
        {
            get { return CurrentManagementGroup.IsConnected; }
        }

        public static void Reconnect()
        {
            CurrentManagementGroup.Reconnect();
        }

        public static void SetCurrentManagementGroup(string serverName)
        {
            emg = new EnterpriseManagementGroup(serverName);
        }


        public static EnterpriseManagementGroup CurrentManagementGroup
        {
            get
            {
                return emg ?? (emg = new EnterpriseManagementGroup(
                                         Registry.GetValue(
                                             @"HKEY_CURRENT_USER\Software\Microsoft\System Center\2010\Service Manager\Console\User Settings",
                                             "SDKServiceMachine", "localhost").ToString()));
            }


        }

        public static ManagementPack GetSystemManagementPack()
        {



            return GetWellKnownManagementPack(SystemManagementPack.System);
        }



        public static ManagementPack GetWellKnownManagementPack(SystemManagementPack systemManagementPack)
        {
            return CurrentManagementGroup.ManagementPacks.GetManagementPack(systemManagementPack);
        }

        public static ManagementPack GetManagementPack(string id)
        {
            return GetManagementPack(new Guid(id));
        }

        public static ManagementPack GetManagementPack(Guid guid)
        {
            return mpCache.ContainsKey(guid) ? mpCache[guid] : CurrentManagementGroup.ManagementPacks.GetManagementPack(guid);
        }

        public static ManagementPack GetManagementPack(string name, string keyToken, Version version)
        {
            return CurrentManagementGroup.ManagementPacks.GetManagementPack(name, keyToken, version);
        }

        public static ManagementPack GetManagementPack(string name, Version version)
        {
            return CurrentManagementGroup.ManagementPacks.GetManagementPack(name, null, version);
        }
        
        public static ManagementPackObjectTemplate GetTemplateFromName(string templateName)
        {
            var criteria = new ManagementPackObjectTemplateCriteria(string.Format("Name = '{0}'", templateName));
            IList<ManagementPackObjectTemplate> templates =
                CurrentManagementGroup.Templates.GetObjectTemplates(criteria);
            ManagementPackObjectTemplate template = templates.FirstOrDefault();
            if (template == null)
            {
                throw new InvalidOperationException(string.Format("Template '{0}' not found", template));
            }
            return template;
        }

        internal static EnterpriseManagementObject GetSingletonObject(ManagementPackClass managementPackClass)
        {
            const string criteriaString = "DisplayName IS NOT NULL";
            var criteria = new EnterpriseManagementObjectCriteria(criteriaString, managementPackClass);
            var reader =
                CurrentManagementGroup.EntityObjects.GetObjectReader<EnterpriseManagementObject>(criteria,
                                                                                                   ObjectQueryOptions.
                                                                                                       Default);
            var enterpriseManagementObject = reader.FirstOrDefault();
          
            return enterpriseManagementObject;
        }

        private static EnterpriseManagementObject GetEnterpriseManagementObject(string criteriaString,
                                                                                ManagementPackClass managementPackClass)
        {
            var criteria = new EnterpriseManagementObjectCriteria(criteriaString, managementPackClass);
            var reader =
                CurrentManagementGroup.EntityObjects.GetObjectReader<EnterpriseManagementObject>(criteria,
                                                                                                   ObjectQueryOptions.
                                                                                                       Default);
            var enterpriseManagementObject = reader.FirstOrDefault();
        
            return enterpriseManagementObject;
        }
 

        internal static ManagementPackTypeProjection GetTypeProjection(Guid typeProjectionId)
        {
            return CurrentManagementGroup.EntityTypes.GetTypeProjection(typeProjectionId);
        }

        internal static ManagementPackTypeProjection GetTypeProjection(string className, ManagementPack managementPack)
        {
            return CurrentManagementGroup.EntityTypes.GetTypeProjection(className, managementPack);
        }

        internal static ManagementPackTypeProjection GetTypeProjection(string typeProjectionId)
        {
            return GetTypeProjection(new Guid(typeProjectionId));
        }

        internal static IList<ManagementPackTypeProjection> GetTypeProjections(ICollection<Guid> ids)
        {
            return CurrentManagementGroup.EntityTypes.GetTypeProjections(ids);
        }

        internal static IList<ManagementPackTypeProjection> GetTypeProjections(ManagementPackTypeProjectionCriteria criteria)
        {
            return CurrentManagementGroup.EntityTypes.GetTypeProjections(criteria);
        }


        public static IObjectReader<EnterpriseManagementObject> GetObjectReader(
            EnterpriseManagementObjectCriteria criteria, ObjectQueryOptions options)
        {
            return CurrentManagementGroup.EntityObjects.GetObjectReader<EnterpriseManagementObject>(criteria, options);
        }

        public static IObjectProjectionReader<EnterpriseManagementObject> GetObjectProjectionReader(
            ObjectProjectionCriteria criteria, ObjectQueryOptions options)
        {


            return CurrentManagementGroup.EntityObjects.GetObjectProjectionReader<EnterpriseManagementObject>(criteria, options);
        }


 


        public static ManagementPackClass GetClass(Guid guid)
        {

            return CurrentManagementGroup.EntityTypes.GetClass(guid);

        }

        public static ManagementPackClass GetClass(string guidString)
        {

            return CurrentManagementGroup.EntityTypes.GetClass(new Guid(guidString));

        }

        public static ManagementPackClass GetClass(string className, ManagementPack managementPack)
        {

            return CurrentManagementGroup.EntityTypes.GetClass(className, managementPack);

        }

        public static IList<ManagementPackClass> GetClasses(Guid[] guids)
        {

            return CurrentManagementGroup.EntityTypes.GetClasses(guids);

        }

        public static IList<ManagementPackClass> GetClasses(ManagementPackClassCriteria classCriteria)
        {

            return CurrentManagementGroup.EntityTypes.GetClasses(classCriteria);

        }

        public static ManagementPackEnumeration GetEnumeration(Guid id)
        {

            return CurrentManagementGroup.EntityTypes.GetEnumeration(id);

        }


        //public static ManagementPackDataSourceModuleType GetSchedulerDataSourceModule()
        //{
        //    return (ManagementPackDataSourceModuleType)SCSMServer.SystemLibrary.GetModuleType("System.Scheduler");
        //}

        //public static ManagementPackWriteActionModuleType GetWorkflowTaskWriteActionModule()
        //{
        //    return (ManagementPackWriteActionModuleType)SCSMServer.MicrosoftSystemCenterSubscriptions.GetModuleType("Microsoft.EnterpriseManagement.SystemCenter.Subscription.WindowsWorkflowTaskWriteAction");
        //}

        //public static EnterpriseManagementObjectProjection GetIncidentProjection()
        //{
        //    return new EnterpriseManagementObjectProjection(CurrentManagementGroup, CommonClasses.IncidentClass);
        //}

        /*
         * AEA081C5-9C1A-1CF0-5378-5D8D3A1B38B8
         * AE88E38D-AA65-5190-A10D-C579D83D3B92
         */


        //public static EnterpriseManagementObjectProjection GetChangeManagementProjection()
        //{
        //    return new EnterpriseManagementObjectProjection(CurrentManagementGroup, CommonClasses.ChangeRequestClass);
        //}

        //public static EnterpriseManagementObjectProjection GetManualActivityProjection()
        //{
        //    return new EnterpriseManagementObjectProjection(CurrentManagementGroup, CommonClasses.ManualActivityClass);
        //}

        //public static EnterpriseManagementObjectProjection GetReviewActivityProjection()
        //{
        //    return new EnterpriseManagementObjectProjection(CurrentManagementGroup, CommonClasses.ReviewActivityClass);
        //}

        public static CreatableEnterpriseManagementRelationshipObject GetRelationshipObject(Guid id)
        {
            var @class = SCSMServer.GetRelationshipClass(id);
            return new CreatableEnterpriseManagementRelationshipObject(CurrentManagementGroup, @class);
        }

        public static CreatableEnterpriseManagementRelationshipObject GetRelationshipObject(string id)
        {
            return GetRelationshipObject(new Guid(id));
        }



        public static ManagementPackRelationship GetRelationshipClass(Guid id)
        {
            return CurrentManagementGroup.EntityTypes.GetRelationshipClass(id);
        }

        public static ManagementPackRelationship GetRelationshipClass(string id)
        {
            return GetRelationshipClass(new Guid(id));
        }

        public static ManagementPackRelationship GetRelationshipClass(string typeName, ManagementPack managementPack)
        {
            return CurrentManagementGroup.EntityTypes.GetRelationshipClass(typeName, managementPack);
        }

        public static ManagementPackRelationship GetRelationshipClass(SystemRelationship relationship)
        {
            return CurrentManagementGroup.EntityTypes.GetRelationshipClass(relationship);
        }

        public static CreatableEnterpriseManagementObject GetCreatableEnterpriseManagementObject(ManagementPackClass typeToCreate)
        {
            return new CreatableEnterpriseManagementObject(CurrentManagementGroup, typeToCreate);
        }

        public static CreatableEnterpriseManagementObject GetCreatableEnterpriseManagementObject(ManagementPackObjectTemplate managementPackObjectTemplate)
        {
            return new CreatableEnterpriseManagementObject(CurrentManagementGroup, managementPackObjectTemplate);
        }

        public static CreatableEnterpriseManagementObject GetCreatableEnterpriseManagementObject(
            ManagementPackObjectTemplate managementPackObjectTemplate, ObjectTemplateCallback callback)
        {
            return new CreatableEnterpriseManagementObject(CurrentManagementGroup, managementPackObjectTemplate, callback);
        }

     




        // add commonly used Management Pack Classes here

        public static T GetObject<T>(Guid id) where T : EnterpriseManagementObject
        {
            return CurrentManagementGroup.EntityObjects.GetObject<T>(id, ObjectQueryOptions.Default);
        }

        public static T GetObject<T>(string id) where T : EnterpriseManagementObject
        {
            return CurrentManagementGroup.EntityObjects.GetObject<T>(new Guid(id), ObjectQueryOptions.Default);
        }

      
    }


}